 package lucasapp.CentralStation_PRO;
//TODO 
// controllo stringhe null in uscita dal parser

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;

public class Stazione extends Activity implements OnSharedPreferenceChangeListener, OnLongClickListener, OnClickListener{

	private static final int SCELTA_STAZIONE=10;
	private static final int DATI_STAZIONE=20;
	private static final int LOC_NON_TROVATA=30;
	private static final int AGG_GRAFICA1=40;
	private static final int AGG_GRAFICA2=50;
	private static final int NON_DISPONIBILE=60;

	private static final int TIPO_CSV=100;
	private static final int TIPO_TXT=110;
	private static final int TIPO_MAIL=120;

	private ProgressDialog mDialogoDownloadHtml;
	private Context mContesto = this;
	private SharedPreferences mPreferenze;
	private Parser mParser;
	private String mRicercaNome="";
	private String mRicercaCodice="";
	private float mCorrezioneOra=0;
	private String mOra="";
	private String[][] mBufferStazione;
	private boolean mCondizioneGrafica1=false;
	private boolean mCondizioneGrafica2=false;
	private boolean mRunFlag=true;
	private boolean mPartenze=false;
	private boolean mArrivi=false;
	private String mHtml;

	private int mVersione = Main.LITE; 
	private AdView adView;

	private Runnable DownloadHTML;		//thread per lettura dati della stazione da Internet 
	private Runnable AggiornaGrafica1;	//thread per mantenere aggiornata la grafica ogni secondo
	private Runnable AggiornaGrafica2;	//thread per mantenere aggiornata la grafica ogni 5 minuti

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //rimuove la top status bar 
		this.mPreferenze = PreferenceManager.getDefaultSharedPreferences(this);
		this.mPreferenze.registerOnSharedPreferenceChangeListener(this);
		this.DownloadHTML = new Runnable() { //thread per lettura dati della stazione da Internet 
			@Override
			public void run() {
				if (mPreferenze.getBoolean("KEY_CORREZIONE_ORA_FLAG", true)) {	//get ora atomica se il flag è scaduto
					try {
						mCorrezioneOra = SntpClient.OffsetOrologioLocale(); 	//avvio il client NTP per correggere l'ora del dispositivo
						SharedPreferences.Editor editor = mPreferenze.edit();	
						editor.putFloat("KEY_CORREZIONE_ORA", mCorrezioneOra);	//salvo nelle preferenze il fattore di correzione
						editor.putBoolean("KEY_CORREZIONE_ORA_FLAG",false);		//e un flag per la correzione
						editor.commit();
						Main.LOG("Client NTP: offset locale " + new DecimalFormat("0.000").format(mCorrezioneOra) + " ms");
					} catch (Exception e) {
						Main.LOG("Eccezione client NTP " + e);
						finish();
					}
				} else	//altrimenti la recupero dalle preferenze
				{
					mCorrezioneOra=mPreferenze.getFloat("KEY_CORREZIONE_ORA", 0);		//leggo il fattore di correzione dalle preferenze
				}
				//http://mobile.viaggiatreno.it/vt_pax_internet/mobile/stazione
				String indirizzo= "http://mobile.viaggiatreno.it/vt_pax_internet/mobile/stazione";	//indirizzo http per la pagina delle stazioni
				ArrayList<NameValuePair> parametriPost= new ArrayList<NameValuePair>();	//parametri per il post http
				parametriPost.add(new BasicNameValuePair("stazione", mRicercaNome));	//aggiungo il nome della stazione
				parametriPost.add(new BasicNameValuePair("lang", "IT"));				//lingua italiana
				if (mRicercaCodice.length()>1)
					parametriPost.add(new BasicNameValuePair("codiceStazione", mRicercaCodice));	//aggiungo il codice della stazione
				mHtml = new String();
				try {
					mHtml = MyHttpClient.PostHttp(indirizzo, parametriPost);	//eseguo il post http
				} catch (Exception e) {
					Main.LOG("Eccezione download (post) dati " + e);
					finish();
				}
				if (!mHtml.contentEquals("")) {
					int ricerca1=mHtml.indexOf("Risultati ricerca");
					int ricerca2=mHtml.indexOf("Cerca Treno (Stazione)");
					int ricerca3=mHtml.indexOf("localita&#039; non trovata");
					int ricerca4=mHtml.indexOf("Servizio non disponibile");

					Message msg = new Message();
					if (ricerca1>0 && ricerca2==-1 && ricerca3==-1){	//trovati i dati stazione
						Main.LOG("Stazione trovata, inizio parsing");
						msg.arg1=DATI_STAZIONE;
						handler.sendMessage(msg);						//invio handler
					}
					else if (ricerca1==-1 && ricerca2>0 && ricerca3==-1){ 	//necessaria ulteriore ricerca stazione
						Main.LOG("Stazione incerta, inizio parsing");
						mParser = new Parser(); 		//istanzio nuovo parser
						mParser.elencoStazioni(mHtml);
						msg.arg1=SCELTA_STAZIONE;
						handler.sendMessage(msg); 						//invio handler
					}
					else if (ricerca1==-1 && ricerca3>0){	//località non trovata
						Main.LOG("Stazione non trovata: " + mRicercaNome);
						msg.arg1=LOC_NON_TROVATA;
						handler.sendMessage(msg); 						//invio handler
					}
					else if(ricerca4>=0){		//se servizio non disponibile
						Main.LOG("Servizio non disponibile");
						msg.arg1=NON_DISPONIBILE;
						handler.sendMessage(msg);
					}
					else{
						Main.LOG("Problemi letttura HTML");
						msg.arg1=NON_DISPONIBILE;
						handler.sendMessage(msg);
					}
				}
			}
		};

		AggiornaGrafica1 = new Runnable() { //lampeggio pallini
			@Override
			public void run() {
				while(mRunFlag){
					if (mCondizioneGrafica1){ //se i pallini devono lampeggiare
						Message msg = new Message();
						msg.arg1=AGG_GRAFICA1;
						handler.sendMessage(msg); 	//invio handler
					}
					try {
						Thread.sleep(1000);	//resta in sleep per 1 secondo
					} catch (InterruptedException e1) {
						Main.LOG("Errore thread Grafica1; " + e1);
					}					
				}
			}
		};

		AggiornaGrafica2 = new Runnable() { //aggiorna lista treni
			@Override
			public void run() {
				while(mRunFlag){
					if (mCondizioneGrafica2){ //se la lista deve essere aggiornata
						Message msg = new Message();
						msg.arg1=AGG_GRAFICA2;
						handler.sendMessage(msg);	//invio handler
					}
					try {
						Thread.sleep(1000*60); //resta in sleep per 1 minuto
					} catch (InterruptedException e1) {
						Main.LOG("Errore thread Grafica2; " + e1);
					}
				}
			}
		};

		this.mRicercaNome=getIntent().getStringExtra("NOME").trim(); //leggo dall'intent il nome della stazione e elimino eventuali spazi
		if (getPackageName().toLowerCase().contains("_lite")) //se il pacchetto contiene la parola LITE
			this.mVersione = Main.LITE; // la versione è lite
		if (getPackageName().toLowerCase().contains("_pro")) //se il pacchetto contiene la parola PRO
			this.mVersione = Main.PRO; // la versione è pro	

		if (savedInstanceState != null) // Restore UI state from the savedInstanceState.
		{
			this.mRicercaNome = conversione_vocali (this.mRicercaNome.trim()); //converto gli accenti in apostrofi
			this.mRicercaCodice = getIntent().getStringExtra("CODICE"); //leggo dall'intent il codice della stazione
			mHtml = savedInstanceState.getString("HTML");
			if (!mHtml.contentEquals("")){
				partenzeArrivi(false); 	//seleziono i treni in partenza o in arrivo, senza invertire la scelta
				aggiornaGrafica();		//aggiorno tabella
			}
		}
		else //normale avvio dell'app quando non è stato salvato lo stato	
		{ 
			if (this.mRicercaNome.length()>2){	//inizio download se ho almeno 3 lettere nel nome della stazione
				this.mRicercaNome = conversione_vocali (this.mRicercaNome.trim()); //converto gli accenti in apostrofi e elimino gli spazi all'inizio o alla fine
				this.mRicercaCodice = getIntent().getStringExtra("CODICE"); //leggo dall'intent il codice della stazione
				startDownload();	
			} 
			else
				showDialog(LOC_NON_TROVATA);	//altrimenti dialogo LOCALITA' NON TROVATA
		}

		//faccio partire i thread per gestire la grafica
		Thread mAggiornaGrafica1 = new Thread(AggiornaGrafica1); 
		mAggiornaGrafica1.start();
		Thread mAggiornaGrafica2 = new Thread(AggiornaGrafica2);
		mAggiornaGrafica2.start();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// Store UI state to the savedInstanceState.
		// This bundle will be passed to onCreate on next call.
		outState.putString("HTML", mHtml);
		super.onSaveInstanceState(outState);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		MenuInflater inflater = getMenuInflater();	//visualizza menu opzioni
		inflater.inflate(R.menu.menu_stazione, menu);
		return true; 
	}

	@Override
	protected void onDestroy() {
		if (adView != null)
			adView.destroy();
		mRunFlag=false;	//prima di chiudere l'activity esco dai tread che aggiornano la grafica 
		super.onDestroy();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) { //gestione menu "tasto destro"
		if (item.getItemId() == R.id.preferenze) {	
			Intent menuPreferenze = new Intent(this, MenuPreferenze.class); //visualizzo menu preferenze
			startActivity(menuPreferenze);			
		} else if (item.getItemId() == R.id.partenzeArrivi) {
			partenzeArrivi(true);	//seleziono i treni in partenza o in arrivo invertendo la scelta
			aggiornaGrafica();		//aggiorna la grafica
		} else if (item.getItemId() == R.id.ultime) {
			Intent result = new Intent();
			setResult(Activity.RESULT_OK, result); //visualizzo i treni preferiti, col dialogo nell'activity main
			finish();	
		} else if (item.getItemId() == R.id.esporta){	//esporto su file csv o txt
			esportaTxtCsv();		
		} else if (item.getItemId() == R.id.condividi){	//esporto su file csv o txt
			condividiTxt();		
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {	//aggiornamento dialoghi
		super.onPrepareDialog(id, dialog, args);
		switch(id){
		case SCELTA_STAZIONE:	//dialogo per scegliere la stazione esatta
			String[][] elencoStazioni = new String [2][this.mParser.numeroStazioni];
			elencoStazioni = this.mParser.getElencoStazioni();
			ArrayAdapter<CharSequence> itemsAdapter1 = new ArrayAdapter<CharSequence>(this,android.R.layout.select_dialog_singlechoice);
			for (int i=0; i<this.mParser.numeroStazioni; i++){
				itemsAdapter1.add(elencoStazioni[1][i]);	//aggiungo le stazioni alla lista
			}	 
			AlertDialog alert1 = (AlertDialog) dialog; 
			alert1.getListView().setAdapter(itemsAdapter1); 
			break;
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {	//gestione dialoghi
		super.onCreateDialog(id);
		Dialog dialog=null;
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		switch(id){
		case SCELTA_STAZIONE: 	//dialogo per scegliere la stazione esatta
			builder.setCancelable(false);
			builder.setTitle(getResources().getString(R.string.stazione_titolo_selezione));
			ArrayAdapter<CharSequence> itemsAdapter1 = new ArrayAdapter<CharSequence>(this,android.R.layout.select_dialog_singlechoice);
			builder.setAdapter(itemsAdapter1, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int item) {
					dialog.dismiss();
					String[][] elencoStazioni = new String [2][mParser.numeroStazioni];
					elencoStazioni = mParser.getElencoStazioni();
					mRicercaCodice=elencoStazioni[0][item]; //aggiungo il codice della stazione
					mRicercaNome=elencoStazioni[1][item];	//oltre al suo nome
					Main.LOG("Scelta la stazione di " + mRicercaNome);
					startDownload();	//nuova ricerca stazione
				}
			});
			break;
		case LOC_NON_TROVATA:	//dialogo per le stazioni non trovate o con nome strano
			builder.setTitle(R.string.stazione_titolo_errore);
			builder.setMessage(R.string.stazione_messaggio_errore);
			builder.setCancelable(false);
			builder.setPositiveButton(R.string.stazione_pulsante_riprova, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int id) { //pulsante per uscire dall'activity
					dialog.dismiss();
					finish();
				}
			});
			break;
		case NON_DISPONIBILE:	//dialogo per quando il server trenitalia non è disponibile
			builder.setTitle(R.string.stazione_titolo_non_disponibile);
			builder.setMessage(R.string.stazione_messaggio_non_disponibile);
			builder.setCancelable(false);
			builder.setPositiveButton(R.string.stazione_pulsante_OK, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int id) { //pulsante per uscire dall'activity
					dialog.dismiss();
					finish();
				}
			});
			break;
		}
		dialog = builder.create();
		return dialog;
	}

	@Override
	public void onClick(View v) {	//pressione breve del touch
		if (v.getId() == R.id.stazione_partenzeArrivi) {
			partenzeArrivi(true);	//seleziono i treni in partenza o in arrivo invertendo la scelta
			aggiornaGrafica();		//aggiorno la grafica
		}
		else if (v.getId() == R.id.stazione_ora) 
			startDownload();		//aggiorno dati
		else if (v.getId() == R.id.stazione_nome){
			Intent result = new Intent();
			setResult(Activity.RESULT_OK, result); //visualizzo i treni preferiti, col dialogo nell'activity main
			finish();
		}
	}

	@Override
	public boolean onLongClick(View v) { //pressione lunga del touch
		if ((v.getId()-50>=0) && (v.getId()-50<this.mBufferStazione[0].length)){ //se l'id è compreso nei range attesi
			Main.LOG("Scelto treno numero " + this.mBufferStazione[1][v.getId()-50]);
			Intent treno = new Intent(this.mContesto, Treno.class);
			treno.putExtra("NUMERO_TRENO", this.mBufferStazione[1][v.getId()-50]);
			treno.putExtra("BINARIO", this.mBufferStazione[5][v.getId()-50]);		//passo binario treno
			treno.putExtra("PARTENZE", this.mPartenze);	//se true visualizzo destinazione
			treno.putExtra("ARRIVI", this.mArrivi);		//se true visualizzo provenienza
			startActivity(treno); //avvio activity treno passando alcuni dati base
		}
		return false;
	}

	private Handler handler = new Handler() { 
		@Override
		public void handleMessage(Message msg) { //gestisco la grafica
			switch (msg.arg1){
			case DATI_STAZIONE:
				mDialogoDownloadHtml.dismiss(); //nascondo finestra spinner
				partenzeArrivi(false); 	//seleziono i treni in partenza o in arrivo, senza invertire la scelta
				gestionePreferiti();	//gestisco i preferiti
				aggiornaGrafica(); 		//aggiorno tabella
				break;
			case SCELTA_STAZIONE:
				mDialogoDownloadHtml.dismiss();	//nascondo finestra spinner
				showDialog(SCELTA_STAZIONE);	//visualizzo dialogo
				break;
			case LOC_NON_TROVATA:
				mDialogoDownloadHtml.dismiss();	//nascondo finestra spinner
				showDialog(LOC_NON_TROVATA);	//visualizzo dialogo
				break;
			case AGG_GRAFICA1:
				for (int k=300;k<300+mBufferStazione[0].length;k++) //per ogni riga della tabella
				{
					TextView tempTV = (TextView) findViewById(k);
					if (tempTV.getText().toString().contains("●")){				//se ci sono i pallini
						if (tempTV.getText().toString().contentEquals(" ●")) 	//li faccio lampeggiare
							tempTV.setText("● ");								//cambiando la loro posizione
						else
							tempTV.setText(" ●");
					}
				}
				TextView mOraTV = (TextView) findViewById(R.id.stazione_ora);	
				if (mOraTV.getText().toString().contains(":")){						//se ci sono i duepunti nell'ora
					mOraTV.setText(mOraTV.getText().toString().replace(":", " ")); 	//li faccio lampeggiare
				}else{
					mOraTV.setText(mOraTV.getText().toString().replace(" ", ":"));	//sostituendoli con uno spazio
				}
				break;
			case AGG_GRAFICA2:
				partenzeArrivi(false); 	//seleziono i treni in partenza o in arrivo, senza invertire la scelta
				aggiornaGrafica();		//aggiorno tabella
				break;
			case NON_DISPONIBILE:
				mDialogoDownloadHtml.dismiss();	//nascondo finestra spinner
				showDialog(NON_DISPONIBILE);	//visualizzo dialogo
				break;
			}
		}
	};

	/**
	 *Visualizza lo spinner e esegue il thread per il download dei dati
	 */
	private void startDownload(){
		disableRotation(this);	//blocco la rotazione dello schermo
		//visualizzo un progressdialog con uno spinner indeterminato e un messaggio
		this.mDialogoDownloadHtml = ProgressDialog.show(this.mContesto, getResources().getString(R.string.stazione_titolo_download), getResources().getString(R.string.stazione_messaggio_download), true,	false);
		this.mCondizioneGrafica1=false;		//per non eseguire aggiornamenti della grfica durante il download
		this.mCondizioneGrafica2=false;
		Thread mDownloadHTML = new Thread(DownloadHTML);
		mDownloadHTML.start(); 							// eseguo il thread
	}

	/**
	 *Gestisce le stazioni scelte per ultime dall'utente salvandole nelle preferenze
	 */
	private void gestionePreferiti(){
		enableRotation(this); //riabilito la rotazione dello schermo disabilitata prima del download
		String prefNome [] = new String[5];
		String prefCodice [] = new String[5];
		this.mRicercaNome=conversione_vocali(this.mParser.nomeStazione);
		int stato=5;
		int i=0;
		for (i=0;i<=4;i++){ //per tutte e 5 le preferenze
			prefNome[i] = this.mPreferenze.getString("KEY_PREF_NOME_"+i, "");		//leggo il nome
			prefCodice[i] = this.mPreferenze.getString("KEY_PREF_CODICE_"+i, "");	//leggo il codice
			if (this.mRicercaNome.contentEquals(prefNome[i])){	//se il nome è già stato salvato
				stato=i;	//aggiorno lo stato della matrice di scambio
			}
		}
		final int[][] matScambio = {	//matrice di scambio delle preferenze; riga: preferenza, colonna: stato
				{1, 0, 0, 0, 0, 0},
				{2, 2, 1, 1, 1, 1},
				{3, 3, 3, 4, 2, 2},
				{4, 4, 4, 2, 3, 3}};			
		SharedPreferences.Editor editor = this.mPreferenze.edit();
		editor.putString("KEY_PREF_NOME_0",this.mRicercaNome);
		editor.putString("KEY_PREF_CODICE_0",this.mRicercaCodice);
		editor.putString("KEY_PREF_NOME_1",prefNome[matScambio[0][stato]]);
		editor.putString("KEY_PREF_NOME_2",prefNome[matScambio[1][stato]]);
		editor.putString("KEY_PREF_NOME_3",prefNome[matScambio[2][stato]]);
		editor.putString("KEY_PREF_NOME_4",prefNome[matScambio[3][stato]]);
		editor.putString("KEY_PREF_CODICE_1",prefCodice[matScambio[0][stato]]);
		editor.putString("KEY_PREF_CODICE_2",prefCodice[matScambio[1][stato]]);
		editor.putString("KEY_PREF_CODICE_3",prefCodice[matScambio[2][stato]]);
		editor.putString("KEY_PREF_CODICE_4",prefCodice[matScambio[3][stato]]);
		editor.commit();
	}

	/**
	 *Parsa i dati in modo da separare le partenze e gli arrivi su due schermate diverse, aggiorna l'ora
	 *@param inverti se true inverte le partenze con gli arrivi
	 */
	private void partenzeArrivi(boolean inverti){
		Main.LOG("Parsing");
		setContentView(R.layout.stazione); //-->imposta la grafica dell'activity
		if (this.mVersione==Main.LITE){ //se lite aggiungo pubblicita'
			adView = new AdView(this, AdSize.SMART_BANNER, "a14fc0f8cc4fef8"); // crea l'oggetto adView
			((LinearLayout) findViewById(R.id.stazioneADS)).addView(adView); // Aggiungi l'annuncio al layout segnaposto
			adView.loadAd(new AdRequest()); // Carica l'ads
		}
		//ora = DateFormat.format("kk:mm", new java.util.Date()).toString(); 
		//DateFormat.format("EEE dd/MM/yy ", new java.util.Date()).toString()		
		this.mOra = new SimpleDateFormat("HH:mm").format(new Date((long) (System.currentTimeMillis() + mCorrezioneOra))); //correggo l'ora locale
		this.mParser = new Parser(); 			//istanzio nuovo parser
		this.mParser.Stazione(this.mHtml,this.mOra);	//applico il parser all'html
		TextView partenzeArriviTV = (TextView) findViewById(R.id.stazione_partenzeArrivi);
		partenzeArriviTV.setOnClickListener(this);
		//parsing dei dati
		if ((partenzeArriviTV.getText().toString().contentEquals(getResources().getString(R.string.stazione_partenze)) && inverti) || 
				(partenzeArriviTV.getText().toString().contentEquals(getResources().getString(R.string.stazione_arrivi))  && inverti==false)){ //doppia condizione	 
			this.mBufferStazione = new String [6][this.mParser.numeroArrivi];
			this.mBufferStazione = this.mParser.getArrivi();
			partenzeArriviTV.setText(R.string.stazione_arrivi); //imposto arrivi
			this.mPartenze = false;
			this.mArrivi = true;
		}
		else{	
			this.mBufferStazione = new String [6][this.mParser.numeroPartenze];
			this.mBufferStazione = this.mParser.getPartenze();
			partenzeArriviTV.setText(R.string.stazione_partenze); //imposto partenze
			this.mPartenze = true;
			this.mArrivi = false;
		}
	}

	/**
	 *Gestione tabella dinamica
	 */
	private void aggiornaGrafica() {
		Main.LOG("aggiornaGrafica");
		//impostazioni base per grafica
		TextView nomeTV = (TextView) findViewById(R.id.stazione_nome);
		TextView oraTV = (TextView) findViewById(R.id.stazione_ora);
		TextView destinazioneProvenienzaTV = (TextView) findViewById(R.id.stazione_destinazioneProvenienza);
		nomeTV.setOnClickListener(this);
		nomeTV.setText(this.mParser.nomeStazione);	//imposto il nome della stazione
		oraTV.setOnClickListener(this);
		oraTV.setText(this.mOra);		//imposto l'ora	
		TableLayout table = (TableLayout)findViewById(R.id.stazione_table); //dichiarazione della tabella dei TextView
		final float scale = getBaseContext().getResources().getDisplayMetrics().density;
		//sistemo etichetta partenze arrivi
		if (mArrivi == true)
			destinazioneProvenienzaTV.setText(R.string.stazione_provenienza); 	//Arrivi
		if (mPartenze==true)
			destinazioneProvenienzaTV.setText(R.string.stazione_destinazione); 	//Partenze	
		String dimensione = this.mPreferenze.getString("KEY_DIMENSIONE", "Media");
		String stile = this.mPreferenze.getString("KEY_STILE", "Monospace");
		if (getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)	//se schermo portrait
		{
			//cancello righe vecchie tranne le prime 2
			int righeTabella=table.getChildCount();
			if (righeTabella>2)
				table.removeViews(2, righeTabella-2); 
			//aggiungo info treni
			for (int j=0;j<this.mBufferStazione[0].length;j++){	//per ogni due righe
				TableRow cRow0= new TableRow(this);
				cRow0.setOnLongClickListener(this);
				for (int i=0; i<4;i++){ //per ogni colonna della prima riga
					TextView rTextView= new TextView(this);					//Creo la casella di testo
					rTextView.setGravity(Gravity.CENTER);					//gravità e padding
					//Imposto la dimensione del testo
					if (dimensione.contentEquals("Piccola"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,12);	
					if (dimensione.contentEquals("Media"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,15);	
					if (dimensione.contentEquals("Grande"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,18);	
					//Imposto lo stile del testo
					if (stile.contentEquals("Serif"))
						rTextView.setTypeface(Typeface.SERIF);
					if (stile.contentEquals("Sans Serif"))
						rTextView.setTypeface(Typeface.SANS_SERIF);	
					if (stile.contentEquals("Monospace"))
						rTextView.setTypeface(Typeface.MONOSPACE);
					if (j%2==0){											//se riga pari sfondo blu e testo bianco
						rTextView.setBackgroundResource(R.color.bluPannello);
						cRow0.setBackgroundResource(R.color.bluPannello);
						rTextView.setTextColor(getResources().getColor(R.color.biancoPannello));
					}else{													//se riga dispari sfondo bianco e testo blu
						rTextView.setBackgroundResource(R.color.biancoPannello);
						cRow0.setBackgroundResource(R.color.biancoPannello);
						rTextView.setTextColor(getResources().getColor(R.color.bluPannello));
					}
					switch (i){
					case 0:		//categoria
						rTextView.setWidth((int)(55 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[0][j].trim());
						cRow0.addView(rTextView);
						break;
					case 1:		//stazione
						rTextView.setWidth((int)(170 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setEllipsize(TextUtils.TruncateAt.MARQUEE);	//impostazioni per far girare il testo
						rTextView.setMarqueeRepeatLimit(-1);					//ripete all'infinito
						rTextView.setHorizontallyScrolling(true);				//scroll orizzontale
						rTextView.setSingleLine(true);							//blocca il TV a singola linea
						rTextView.setSelected(true);							//per abilitare subito lo scorrere del testo
						rTextView.setText(this.mBufferStazione[2][j].trim());
						cRow0.addView(rTextView); 
						break;
					case 2:		//ora
						rTextView.setWidth((int)(65 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[3][j].trim());
						cRow0.addView(rTextView);
						break;
					case 3:		//segnaposto per pallini
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,15);	//dimensione e stile carattere fissato
						rTextView.setTypeface(Typeface.MONOSPACE);
						rTextView.setWidth((int)(25 * scale + 0.5f));		//larghezza TV con formula
						int minutiTreno = (Integer.parseInt(this.mBufferStazione[3][j].substring(0,2))*60) + Integer.parseInt(this.mBufferStazione[3][j].substring(3,5));
						int ritardo = Integer.parseInt(this.mBufferStazione[4][j]);
						int minutiAttuali = (Integer.parseInt(this.mOra.substring(0,2))*60) + Integer.parseInt(this.mOra.substring(3,5));
						if ((minutiTreno+ritardo)==(minutiAttuali-2)     ||		//abilito pallini sui treni partiti da 1
								(minutiTreno+ritardo)==(minutiAttuali-1) || 	//o due minuti
								(minutiTreno+ritardo)==(minutiAttuali)   || 	//o in partenza ora
								(minutiTreno+ritardo)==(minutiAttuali+1))		//o in partenza tra un minuto
							rTextView.setText(" ●");
						else
							rTextView.setText("  ");
						rTextView.setId(j+300);								//imposto id al TV dei pallini (offset di 300)
						cRow0.addView(rTextView); 
						break;
					}
				}
				cRow0.setId(j+50);		//imposto id alla riga della tabella (offset di 50)
				table.addView(cRow0);	//aggiungo la prima riga alla tabella	

				TableRow cRow1= new TableRow(this);
				cRow1.setOnLongClickListener(this);
				for (int i=0; i<3;i++){ 									//per ogni colonna della seconda riga
					TextView rTextView= new TextView(this);					//Creo la casella di testo
					rTextView.setGravity(Gravity.CENTER);					//gravità e padding
					//Imposto la dimensione del testo
					if (dimensione.contentEquals("Piccola"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,12);	
					if (dimensione.contentEquals("Media"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,15);	
					if (dimensione.contentEquals("Grande"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,18);	
					//Imposto lo stile del testo
					if (stile.contentEquals("Serif"))
						rTextView.setTypeface(Typeface.SERIF);
					if (stile.contentEquals("Sans Serif"))
						rTextView.setTypeface(Typeface.SANS_SERIF);	
					if (stile.contentEquals("Monospace"))
						rTextView.setTypeface(Typeface.MONOSPACE);
					if (j%2==0){											//se riga pari sfondo blu e testo bianco
						rTextView.setBackgroundResource(R.color.bluPannello);
						cRow1.setBackgroundResource(R.color.bluPannello);
						rTextView.setTextColor(getResources().getColor(R.color.biancoPannello));
					}else{													//se riga dispari sfondo bianco e testo blu
						rTextView.setBackgroundResource(R.color.biancoPannello);
						cRow1.setBackgroundResource(R.color.biancoPannello);
						rTextView.setTextColor(getResources().getColor(R.color.bluPannello));
					}
					switch (i){
					case 0:		//numero
						rTextView.setWidth((int)(55 * scale + 0.5f));	//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[1][j].trim());
						cRow1.addView(rTextView);
						break;
					case 1:		//binario reale oppure previsto
						rTextView.setWidth((int)(170 * scale + 0.5f));	//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[5][j].trim());
						cRow1.addView(rTextView);
						break;
					case 2:		//ritardo
						rTextView.setWidth((int)(65 * scale + 0.5f));	//larghezza TV con formula
						if (this.mBufferStazione[4][j].equals("0")) 	//se 0 minuti di ritardo
							rTextView.setText(" ");						//cancello zero
						else{
							rTextView.setText(this.mBufferStazione[4][j]+"'");	//altrimenti aggiungo apostrofo
						}
						cRow1.addView(rTextView);
						break;
					}
				}
				cRow1.setId(j+50);		//imposto id alla riga della tabella (offset di 50)
				table.addView(cRow1);	//aggiungo la seconda riga alla tabella	
			}
		}
		if (getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE) {	//landscape
			//cancello righe vecchie tranne la prima
			int righeTabella=table.getChildCount();
			if (righeTabella>1)
				table.removeViews(1, righeTabella-1); 
			//aggiungo info treni
			for (int j=0;j<this.mBufferStazione[0].length;j++){	//per ogni riga
				TableRow cRow= new TableRow(this);
				cRow.setOnLongClickListener(this);
				for (int i=0; i<7;i++){ //per ogni colonna
					TextView rTextView= new TextView(this);					//Creo la casella di testo
					rTextView.setGravity(Gravity.CENTER);					//gravità e padding
					//Imposto la dimensione del testo
					if (dimensione.contentEquals("Piccola"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,12);	
					if (dimensione.contentEquals("Media"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,15);	
					if (dimensione.contentEquals("Grande"))
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,18);	
					//Imposto lo stile del testo
					if (stile.contentEquals("Serif"))
						rTextView.setTypeface(Typeface.SERIF);
					if (stile.contentEquals("Sans Serif"))
						rTextView.setTypeface(Typeface.SANS_SERIF);	
					if (stile.contentEquals("Monospace"))
						rTextView.setTypeface(Typeface.MONOSPACE);
					rTextView.setPadding(0, 5, 0, 5);
					if (j%2==0){
						rTextView.setBackgroundResource(R.color.bluPannello);					//imposto lo sfondo del TV
						cRow.setBackgroundResource(R.color.bluPannello);						//imposto lo sfondo della riga
						rTextView.setTextColor(getResources().getColor(R.color.biancoPannello));//imposto il colore del testo
					}else{
						rTextView.setBackgroundResource(R.color.biancoPannello);				//imposto lo sfondo del TV
						cRow.setBackgroundResource(R.color.biancoPannello);						//imposto lo sfondo della riga
						rTextView.setTextColor(getResources().getColor(R.color.bluPannello));	//imposto il colore del testo
					}
					switch (i){
					case 0: 		//categoria
						rTextView.setWidth((int)(40 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[0][j].trim());
						cRow.addView(rTextView);
						break;
					case 1:			//numero
						rTextView.setWidth((int)(55 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[1][j].trim());
						cRow.addView(rTextView);
						break;
					case 2:			//stazione
						rTextView.setWidth((int)(150 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setEllipsize(TextUtils.TruncateAt.MARQUEE);	//impostazioni per far girare il testo
						rTextView.setMarqueeRepeatLimit(-1);					//ripete all'infinito
						rTextView.setHorizontallyScrolling(true);				//scroll orizzontale
						rTextView.setSingleLine(true);							//blocca il TV a singola linea
						rTextView.setSelected(true);							//per abilitare subito lo scorrere del testo
						rTextView.setText(this.mBufferStazione[2][j].trim());
						cRow.addView(rTextView);
						break;
					case 3:			//ora
						rTextView.setWidth((int)(55 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setText(this.mBufferStazione[3][j].trim());
						cRow.addView(rTextView);
						break;
					case 4:			//ritardo
						rTextView.setWidth((int)(45 * scale + 0.5f));	//larghezza TV con formula
						if (this.mBufferStazione[4][j].equals("0")) //se 0 minuti di ritardo
							rTextView.setText(" ");					//cancello zero
						else{
							rTextView.setText(this.mBufferStazione[4][j]+"'");	//altrimenti aggiungo apostrofo
						}
						cRow.addView(rTextView);
						break;
					case 5:			//binario reale oppure previsto
						rTextView.setWidth((int)(45 * scale + 0.5f));			//larghezza TV con formula
						rTextView.setEllipsize(TextUtils.TruncateAt.MARQUEE);	//impostazioni per far girare il testo
						rTextView.setMarqueeRepeatLimit(-1);					//ripete all'infinito
						rTextView.setHorizontallyScrolling(true);				//scroll orizzontale
						rTextView.setSingleLine(true);							//blocca il TV a singola linea
						rTextView.setSelected(true);							//per abilitare subito lo scorrere del testo
						rTextView.setText(this.mBufferStazione[5][j].trim());
						cRow.addView(rTextView);
						break;
					case 6:			//segnaposto per pallini
						rTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,15);	//dimensione e stile carattere fissato
						rTextView.setTypeface(Typeface.MONOSPACE);
						rTextView.setWidth((int)(30 * scale + 0.5f));		//larghezza TV con formula
						int minutiTreno = (Integer.parseInt(this.mBufferStazione[3][j].substring(0,2))*60) + Integer.parseInt(this.mBufferStazione[3][j].substring(3,5));
						int ritardo = Integer.parseInt(this.mBufferStazione[4][j]);
						int minutiAttuali = (Integer.parseInt(this.mOra.substring(0,2))*60) + Integer.parseInt(this.mOra.substring(3,5));

						if ((minutiTreno+ritardo)==(minutiAttuali-2)     ||		//abilito pallini sui treni partiti da 1
								(minutiTreno+ritardo)==(minutiAttuali-1) || 	//o due minuti
								(minutiTreno+ritardo)==(minutiAttuali)   || 	//o in partenza ora
								(minutiTreno+ritardo)==(minutiAttuali+1))		//o in partenza tra un minuto
							rTextView.setText(" ●");
						else
							rTextView.setText("  ");
						rTextView.setId(j+300);	//imposto id al TV dei pallini (offset di 300)
						cRow.addView(rTextView); 
						break;
					}
				}
				cRow.setId(j+50);		//imposto id alla riga della tabella (offset di 50)
				table.addView(cRow);	//aggiungo la TableRow alla tabella	
			}
		}
		if (getPackageName().toLowerCase().contains("_lite") && mCondizioneGrafica1==false) //se il pacchetto contiene la parola LITE ed è la prima volta che eseguo il comando
			Toast.makeText(this.mContesto, getResources().getText(R.string.stazione_toast_long_press), Toast.LENGTH_LONG).show();
		this.mCondizioneGrafica1=true;
		this.mCondizioneGrafica2=true;		

		Main.LOG("fine aggiorna grafica");

	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {
		if(arg1.contentEquals("KEY_STILE")||arg1.contentEquals("KEY_DIMENSIONE")){
			aggiornaGrafica();		//aggiorno la grafica
		}
	}

	/**
	 *Converte vocali accentate in vocali apostrofate per maggiore compatibilità col server
	 */
	private String conversione_vocali(String testo){
		String[] chars = {"`","a`","e`","e`","i`","o`","u`"}; 
		String[] codes = {"'","à","é","è","ì","ò","ù"};
		for(int x=0; x<chars.length; x++){
			testo=testo.replace(codes[x],chars[x]);
		}
		return testo;
	}

	/**
	 * Crea un testo ottimizzato e completo utilizzando tutte le informazioni parsate da Internet
	 * 
	 * @param tipo di formato CSV o TXT
	 * @return stringa impaginata
	 */
	private String creaTesto(int tipo){
		String ls = System.getProperty("line.separator"); //separatore di riga
		String cs1 = "";	//separatore di campo intermedio
		String cs2 = "";	//separatore di campo iniziale e finale
		if (tipo==TIPO_TXT){ //se file di testo semplice tab
			cs1 = "\t";
			cs2 = "";
		}
		if (tipo==TIPO_CSV){ //se file csv virgola e virgolette
			cs1 = "\",\"";
			cs2 = "\"";
		}
		if (tipo==TIPO_MAIL){ //testo facile da leggere virgole e spazi
			cs1 = ", ";
			cs2 = "";
		}
		//riga zero
		String riga0 = "Central Station by lucas app" + ls + "Stazione di " + this.mParser.nomeStazione + " alle ore " + this.mOra;
		//riga uno, categoria + numero
		String riga1 = cs2 + getResources().getString(R.string.stazione_cat) + cs1 + getResources().getString(R.string.stazione_numero) + cs1;
		//provenienza - destinazione	
		TextView partenzeArriviTV = (TextView) findViewById(R.id.stazione_partenzeArrivi);
		if (partenzeArriviTV.getText().toString().contentEquals(getResources().getString(R.string.stazione_arrivi)))
			riga1 = riga1 + getResources().getString(R.string.stazione_provenienza) + cs1; 		//Arrivi
		if (partenzeArriviTV.getText().toString().contentEquals(getResources().getString(R.string.stazione_partenze)))
			riga1 = riga1 + getResources().getString(R.string.stazione_destinazione)+ cs1; 	//Partenze
		//orario + ritardo + binario
		riga1 = riga1 + getResources().getString(R.string.stazione_orario) + cs1
				+ getResources().getString(R.string.stazione_ritardo) + cs1
				+ getResources().getString(R.string.stazione_binario) + cs2; 
		//dati
		String dati="";
		for (int j=0;j<this.mBufferStazione[0].length;j++){	//per ogni riga
			for (int i=0; i<6;i++){ //per ogni colonna
				if (i==0) //categoria del treno
					dati = dati + cs2 + this.mBufferStazione[i][j].trim() + cs1;
				if ((i==1)||(i==2)||(i==3)||(i==4)) //numero | stazione | ora | ritardo 
					dati = dati + this.mBufferStazione[i][j].trim() + cs1;
				if (i==5) //binario reale oppure previsto
					dati = dati + this.mBufferStazione[5][j] + cs2;
			}
			dati = dati + ls; //aggiungo separatore di riga
		}
		return riga0 + ls + riga1 + ls + dati; //testo completo
	}

	/**
	 * esporta e salva un testo con estensione .txt o .csv
	 */
	private void esportaTxtCsv(){
		String testo="";
		String ext = "";	//estensione del file
		if (mPreferenze.getBoolean("KEY_CSV", true)){ //se file csv
			testo = creaTesto(TIPO_CSV); //creo file csv
			ext = ".csv";	//estensione csv
		}
		if (mPreferenze.getBoolean("KEY_TXT", false)){ //se file txt
			testo = creaTesto(TIPO_TXT); //creo file txt
			ext = ".txt";	//estensione txt
		}
		//salvo i dati su uSD
		File dir = new File( Environment.getExternalStorageDirectory().getPath() + "/CentralStation/");	//imposto la directory
		dir.mkdirs();
		String ora=DateFormat.format("kkmm_", new java.util.Date()).toString(); 
		String data=DateFormat.format("yyyyMMdd_", new java.util.Date()).toString();	
		File fileEsp = new File(dir, data + ora + this.mParser.nomeStazione + ext); //nuovo file per l'esportazione
		try {
			fileEsp.createNewFile();
			FileOutputStream fileOutputStream =new FileOutputStream(fileEsp);	//abilito output stream
			OutputStreamWriter outputWriter = new OutputStreamWriter(fileOutputStream);
			outputWriter.append(testo); //aggiungo testo
			outputWriter.close();
			fileOutputStream.close();	//chiudo gli stream
			Toast.makeText(this.mContesto, getResources().getString(R.string.stazione_toast_salva)+data+ora+this.mParser.nomeStazione+ext, Toast.LENGTH_LONG).show();
		} catch (Exception e) {
			Main.LOG("Errore esportazione dati " + e);
		}
	}

	/**
	 * condivide le informazioni in formato testo
	 */
	private void condividiTxt(){
		String testo = creaTesto(TIPO_MAIL); //creo file testo
		Intent condividi = new Intent(Intent.ACTION_SEND); //azione invia testo
		condividi.setType("text/plain");
		condividi.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.app_name));
		condividi.putExtra(Intent.EXTRA_TEXT, testo);	//aggiunge il testo
		try {
			startActivity(Intent.createChooser(condividi, getResources().getString(R.string.app_name)));	//invia
			Main.LOG("File LOG inviato");
		} catch (Exception e) {
			Main.LOG("Nessun client e-mail installato" + e);
		}
	}

	// Sets screen rotation as fixed to current rotation setting
	static void disableRotation(Activity activity)
	{       
		final int orientation = activity.getResources().getConfiguration().orientation;
		final int rotation = activity.getWindowManager().getDefaultDisplay().getOrientation();

		// Copied from Android docs, since we don't have these values in Froyo 2.2
		int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
		int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;

		if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO)	{
			SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
			SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
		}

		if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
			if (orientation == Configuration.ORIENTATION_PORTRAIT)
				activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
			else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
				activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		}
		else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) {
			if (orientation == Configuration.ORIENTATION_PORTRAIT) 
				activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
			else if (orientation == Configuration.ORIENTATION_LANDSCAPE) 
				activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
		}
	}

	static void enableRotation(Activity activity)
	{
		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
	}







}
